package se.webbzon.oschi01.worldobject.appearance;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.Node;
import javax.media.j3d.Transform3D;

public class MutableAppearance3D implements Appearance3D {
	
	// The node of this appearance
	private final BranchGroup branchGroup;
	
	// The appearance projected by this mutable appearance 
	private Appearance3D appearance;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new mutable 3D appearance. **/
	public MutableAppearance3D(Appearance3D appearance) throws Appearance3DException {
		if (appearance == null)
			throw new Appearance3DException("The given appearance can not be null!");
		
		branchGroup = new BranchGroup();
		branchGroup.setCapability(BranchGroup.ALLOW_DETACH);
		branchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
		branchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
		branchGroup.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
		
		setAppearance(appearance);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Sets the appearance projected by this mutable appearance. **/
	public void setAppearance(Appearance3D appearance) throws Appearance3DException {
		if (appearance == null)
			throw new Appearance3DException("The given appearance can not be null!");
		
		final Transform3D transform = new Transform3D();
		final boolean visible;
		if (this.appearance == null) {
			appearance.getTransform(transform);
			visible = appearance.getVisible();
		} else {
			((BranchGroup) this.appearance.getJ3dBranch().getParent()).detach();
			this.appearance.getTransform(transform);
			visible = this.appearance.getVisible();
		}
		
		BranchGroup appearanceGroup = new BranchGroup();
		appearanceGroup.setCapability(BranchGroup.ALLOW_DETACH);
		appearanceGroup.addChild(appearance.getJ3dBranch());
		branchGroup.addChild(appearanceGroup);
		
		this.appearance = appearance;
		
		setTransform(transform);
		setVisible(visible);
	}
	
	/** Returns the appearance projected by this mutable appearance. **/
	public Appearance3D getAppearance() {
		return appearance;
	}

	@Override public void onStepEnd() {
		appearance.onStepEnd();
	}

	@Override public void setAnimation(Animation3D animation) {
		appearance.setAnimation(animation);
	}

	@Override public Animation3D getAnimation() {
		return appearance.getAnimation();
	}

	@Override public void getTransform(Transform3D transform) {
		appearance.getTransform(transform);
	}

	@Override public void setTransform(Transform3D transform) {
		appearance.setTransform(transform);
	}

	@Override public int getRenderingOrder() {
		return appearance.getRenderingOrder();
	}

	@Override public boolean getVisible() {
		return appearance.getVisible();
	}

	@Override public void setVisible(boolean visible) {
		appearance.setVisible(visible);
	}

	@Override public BranchGroup getJ3dBranch() {
		return branchGroup;
	}

}
